import { del_articles, getArticles } from '@/services/ant-design-pro/miniModel2';
import {
  add_entity,
  add_label,
  articleConfirm,
  articleReclean,
  del_entity,
  del_label,
  domains,
  entities_list,
  label_list,
} from '@/services/ant-design-pro/miniModel3';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import { history } from '@umijs/max';
import {
  Button,
  Divider,
  Input,
  InputRef,
  message,
  Modal,
  Pagination,
  Popconfirm,
  Select,
  Space,
} from 'antd';
import CanvasHighlighter from 'canvas-highlighter';
import DOMPurify from 'dompurify';
import { cloneDeep } from 'lodash';
import { nanoid } from 'nanoid';
import React, { useEffect, useRef, useState } from 'react';
import './index.less';
const MiniModel3: React.FC = () => {
  const [curModel, setCurModel] = useState<boolean>(false); //当前模式 未标注 仪表罩
  const [list, setList] = useState<any>([]); //文章列表
  const [domainList, setDomainList] = useState<any>([]); //领域列表
  const [pageSize, setPageSize] = useState<any>({ page: 1, per_page: 10 }); //文章翻页
  const [total, setTotal] = useState<number>(0); //文章总数
  const [active, setActive] = useState<number>(0); //当前选中文章的索引
  const [curArticle, setCurArticle] = useState<any>({
    main_body: '',
    id: '',
    domain: '',
    region: '',
    source: '',
    title: '',
  }); //当前显示的文章
  const isInitHtml = useRef<any>(false); //文档内容是否初始化
  const [articleHTML, setArticleHTML] = useState<any>(null); //文档内容 从后台获取的数据
  const articleContRef = useRef<any>(null); //文档容器
  const highlighterRef = useRef<any>(null); //高亮实例
  const [labelName, setLabelName] = useState(''); //新标签的name
  const inputRef = useRef<InputRef>(null); //新标签的输入框容器
  const [optionList, setOptionList] = useState<any[]>([]); //标签下拉列表数据
  const [selectedItems, setSelectedItems] = useState(''); //标签选中
  const [isModalLabelOpen, setIsModalLabelOpen] = useState<boolean>(false); //删除标签提示框
  const [curDelLabel, setCurDelLabel] = useState(null); //当前点击要删除的标签
  const [domain, setDomain] = useState<any>([]); //领域
  const [title, setTitle] = useState<string>(''); //标题
  const [source, setSource] = useState<string>(''); //来源
  const [region, setRegion] = useState<string>(''); //地区

  const colorList = [
    'rgba(96, 217, 164, 0.4)',
    'rgba(229,77,66,0.4)',
    'rgba(251,189,8,0.4)',
    'rgba(141,197,63,0.4)',
    'rgba(156,38,176,0.4)',
    'rgba(28,187,180,0.4)',
    'rgba(0,129,255,0.4)',
    'rgba(103,57,182,0.4)',
    'rgba(57,181,74,0.4)',
    'rgba(165,103,63,0.4)',
    'rgba(170,170,170,0.4)',
    'rgba(224,57,151,0.4)',
    'rgba(135,153,163,0.4)',
    'rgba(243,123,29,0.4)',
    'rgba(255,255,255,0.4)',
  ];
  useEffect(() => {
    document.title = '人工标注文档'; //设置标题
  }, []);

  const { Option } = Select;

  //切换未标注和已标注

  const toggleModel = (b: any) => {
    setDomain([]);
    setTitle('');
    setSource('');
    setRegion('');
    setCurModel(b);
    setPageSize({ page: 1, per_page: 10 });
  };

  //根据标签获取对应的颜色
  const getConfigColor = (labelName: any) => {
    //根据name获取对应的索引 然后匹配colorList

    let index = highlighterRef.current.optionList.findIndex((item: any) => item === labelName) || 0;

    let config = {
      rect: {
        fill: colorList[index], //背景色
        visible: true,
      },
      line: {
        stroke: '',
        strokeWidth: 1,
        visible: false,
      },
    };
    return config;
  };

  //切换文章
  const toggleActive = async (item: any, index: any) => {
    highlighterRef.current.clear();
    setActive(index);
    let docHtml = item?.main_body;
    let htmlCon = docHtml
      .split('\n')
      .map((p: any) => `<p>${p}</p>`)
      .join('');
    let sanitizeHtml = DOMPurify.sanitize(htmlCon); //使用DOMPurify.sanitize()方法过滤HTML字符串 防止XSS攻击
    setArticleHTML(sanitizeHtml);
    setCurArticle(item);
  };

  //获取标签列表
  const getTagList = async () => {
    let res = await label_list({
      article_id: list[active]?.id,
    });
    if (res.code === 0) {
      if (res.data) {
        setOptionList(res.data);
        //选中
        if (res.data.length > 0) {
          setSelectedItems(res.data[0]);
        } else {
          setSelectedItems('');
        }
      }
    }
  };

  //标签输入
  const onNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setLabelName(event.target.value);
  };

  //添加标签
  const addItem = async (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {
    e.preventDefault();
    if (!labelName) {
      message.warning('请输入标签名称');
      return;
    }
    //判断labelName与optionList中是否存在
    if (!optionList.find((item) => item === labelName)) {
      let res = await add_label({
        name: labelName,
        article_id: curArticle.id,
      });
      if (res.code === 0) {
        message.success('添加标签成功');
        setOptionList((prev) => [...prev, labelName]);
        setLabelName('');
        setTimeout(() => {
          inputRef.current?.focus();
        }, 0);
        if (optionList.length === 0) {
          setSelectedItems(labelName);
        }
      } else {
        message.error(res.msg);
      }
    } else {
      message.warning('标签已存在');
    }
  };

  //删除标签
  const delItem = (e: any, item: any) => {
    e.preventDefault();
    e.stopPropagation();
    setIsModalLabelOpen(true); //弹窗提示确认删除
    setCurDelLabel(item); //选中当前要删除的对象
  };

  //删除标签提示框确定
  const handleLabelOk = async () => {
    setIsModalLabelOpen(false);
    let res = await del_label({
      name: curDelLabel,
      article_id: curArticle.id,
    });
    if (res.code === 0) {
      message.success('删除标签成功');
      setOptionList(optionList.filter((o: any) => o !== curDelLabel));
      //如果删除的是当前选中的标签 则将选中往下一位 如果没有选项，则置空
      if (optionList.length === 0) {
        setSelectedItems('');
      } else {
        if (curDelLabel === selectedItems) {
          setSelectedItems(optionList.filter((o: any) => o !== curDelLabel)[0]);
        }
      }
    } else {
      message.error(res.msg);
    }
  };

  //删除标签提示框取消
  const handleLabelCancel = () => {
    setIsModalLabelOpen(false);
  };

  //根据标签获取实体
  const getEntitiesList = async (id: any) => {
    highlighterRef.current.clear();
    let res = await entities_list({
      article_id: id ? id : curArticle.id,
    });
    if (res.code === 0) {
      let rangeList = res?.data?.article_entities.map((o: any) => ({
        ...o,
        start: o.start_json,
        end: o.end_json,
        text: o.target_content,
        config: getConfigColor(o.tag),
        id: nanoid(),
        article_entity_id: o.id,
      }));
      highlighterRef.current.renderRanges(rangeList);
    } else {
      message.error(res.msg);
    }
  };

  //添加实体
  const addEntity = async (range: any) => {
    if (!highlighterRef.current.selectedItems) {
      message.warning('请先创建标签或选中标签');
      return;
    }
    range.config = getConfigColor(highlighterRef.current.selectedItems);
    let data: any = {
      article_id: highlighterRef.current.curArticle.id || '',
      target_content: range.text,
      tag: highlighterRef.current.selectedItems || '',
      start: range.start.offset,
      end: range.end.offset,
      start_json: range.start,
      end_json: range.end,
      position: range.position,
    };

    let res = await add_entity(data);
    if (res.code === 0) {
      message.success('标注完成');
      let article_entity = res.data.article_entity;
      let copyRange = cloneDeep(range);
      copyRange.id = nanoid(); //添加一个随机id 用于高亮组件
      copyRange.article_entity_id = article_entity.id; //原后台记录的id 用于删除

      console.log(copyRange);

      highlighterRef.current.addRange(copyRange);
      window?.getSelection()?.removeAllRanges();
    } else {
      message.error(res.msg);
    }
  };

  //删除实体
  const delEntity = async (id: any) => {
    console.log(id);

    let info = highlighterRef.current.getRange(id); //获取当前选中的实体的信息
    console.log(info);

    let res = await del_entity({
      article_entity_id: info.article_entity_id, //当前点击的实体的后台id
    });
    if (res.code === 0) {
      message.success('删除实体成功');
      highlighterRef.current?.deleteRange(id); //删除选中的文本
    } else {
      message.error(res.msg);
    }
  };

  //鼠标选中
  const handleMouseUp = () => {
    const range = highlighterRef.current.getSelectionRange();
    //选中范围
    if (range) {
      let end = highlighterRef.current?.getSelectionPosition()?.end; //选中文本的结束位置
      if (end < 0) {
        end = 0;
      }

      //获取articleContRef距离页面左上角的距离 x = left ; y = top
      const containerOffset = articleContRef.current?.getBoundingClientRect();

      //点赞modal位置 因为end返回的位置是距离页面左上角的距离 所以要减去articleContRef距离页面左上角的距离
      let left = end?.left - containerOffset?.x;
      let top = end?.top - containerOffset?.y + 20;
      //在一行的最后一个字位置会偏移 重新计算
      if (left === 0) {
        left = containerOffset.width - 5;
        top = top - 26;
      }
      let position = {
        top: top + 'px',
        left: left + 'px',
      };
      range.position = position;
      setTimeout(() => {
        addEntity(range); //添加实体
      }, 200);
    } else {
    }
  };

  //鼠标点击
  const handleDocumentClick = (event: any) => {
    // 通过传入点击位置获取 range id
    const id = highlighterRef.current.getRangeIdByPointer(event.pageX, event.pageY);
    if (id) {
      //调用删除id
      delEntity(id);
    }
  };

  //获取文章
  const handleGetArticles = async () => {
    let res = await getArticles({
      page: pageSize.page,
      per_page: pageSize.per_page,
      status: !curModel ? 'labeling' : 'labeled',
    });
    if (res.code === 0) {
      setTotal(res?.data?.total_count || 0);
      setList(res?.data?.articles || []);

      if (res?.data?.articles.length > 0) {
        let docHtml = res?.data?.articles[active]?.main_body;
        let htmlCon = docHtml
          .split('\n')
          .map((p: any) => `<p>${p}</p>`)
          .join('');
        let sanitizeHtml = DOMPurify.sanitize(htmlCon); //使用DOMPurify.sanitize()方法过滤HTML字符串 防止XSS攻击
        setArticleHTML(sanitizeHtml);
        setCurArticle(res?.data?.articles[active]);

        isInitHtml.current = true; //文档内容已初始化
        if (!highlighterRef.current) {
          highlighterRef.current = new CanvasHighlighter(articleContRef.current);
          articleContRef.current.addEventListener('mouseup', handleMouseUp);
          articleContRef.current.addEventListener('click', handleDocumentClick);
        }
      } else {
        setArticleHTML('');
        setCurArticle({
          main_body: '',
          id: '',
          domain: '',
          region: '',
          source: '',
          title: '',
        });
      }
    } else {
      message.error(res.msg);
    }
  };

  //翻页
  const changePageSize = async (page: any, pageSize: any) => {
    setActive(0);
    setPageSize({
      page: page,
      per_page: pageSize,
    });
  };

  //获取全部领域列表
  const getDomains = async () => {
    let res = await domains({});
    if (res.code === 0) {
      let list = res.data.map((option: any) => ({
        label: option.name,
        value: option.id,
        id: option.id,
      }));
      setDomainList(list);
    } else {
      message.error(res.msg);
    }
  };

  //获取全部领域列表
  useEffect(() => {
    getDomains();
  }, []);

  //获取文章内容
  useEffect(() => {
    handleGetArticles(); //文章列表
  }, [pageSize]);

  //检测列表数据和选中
  useEffect(() => {
    if (list.length > 0 && active >= 0) {
      getTagList(); //标签列表
      highlighterRef.current.curArticle = list[active];
    }
  }, [active, list]);

  //默认选中文档 来源 领域 地区
  useEffect(() => {
    const { domain, region, source, title } = curArticle;
    if (title) {
      setTitle(title);
    }
    if (domain) {
      setDomain(domain);
    }
    if (source) {
      setSource(source);
    }
    if (region) {
      setRegion(region);
    }
  }, [curArticle]);

  //标签选中
  const selectChange = (value: any) => {
    setSelectedItems(value);
  };

  const domainChange = (e: any) => {
    setDomain(e);
  };
  const titleChange = (e: any) => {
    setTitle(e.target.value);
  };
  const sourceChange = (e: any) => {
    setSource(e.target.value);
  };
  const regionChange = (e: any) => {
    setRegion(e.target.value);
  };

  //确认完成
  const submitLabel = async () => {
    if (title === '') {
      message.error('请输入该文档的名称');
      return;
    }
    if (source === '') {
      message.error('请输入该文档的来源');
      return;
    }
    if (domain.length === 0) {
      message.error('请选择该文档所涵盖的领域');
      return;
    }

    if (region === '') {
      message.error('请输入该文档所涉地区');
      return;
    }
    let body = {
      title,
      domain_ids: domain,
      source,
      region,
      article_id: curArticle.id,
    };
    let res = await articleConfirm(body);
    if (res.code === 0) {
      message.success('数据处理完成，已存入本地知识库');
      handleGetArticles();

      //清除来源 领域 地区的输入 和optionsList =[]
      setTitle('');
      setDomain([]);
      setSource('');
      setRegion('');
      setOptionList([]);
      setSelectedItems('');
    } else {
      message.error(res.msg);
    }
  };
  //全部文章确认完成
  // const submitAllLabel = async () => {
  // let res = await articleConfirm({});
  // if (res.code === 0) {
  //   message.success('数据处理完成，已存入本地知识库');
  //   handleGetArticles();

  //   //清除来源 领域 地区的输入 和optionsList =[]
  //   setTitle('');
  //   setDomain([]);
  //   setSource('');
  //   setRegion('');
  //   setOptionList([]);
  //   setSelectedItems('');
  // } else {
  //   message.error(res.msg);
  // }
  // }

  const cancel = () => {};

  //标签选中变化
  useEffect(() => {
    if (selectedItems) {
      highlighterRef.current.selectedItems = selectedItems;
      getEntitiesList(null);
    } else {
      highlighterRef?.current?.clear();
    }
  }, [selectedItems]);

  //标签选中变化
  useEffect(() => {
    if (optionList && highlighterRef.current) {
      highlighterRef.current.optionList = optionList;
      getEntitiesList(null);
    }
  }, [optionList, highlighterRef.current]);

  //去上传文件
  const goToUrl = () => {
    history.push('/miniModel1');
  };
  //去标记文档
  const goToUrl2 = () => {
    history.push('/miniModel2');
  };

  //回退到清洗
  const returnToClean = async () => {
    let res = await articleReclean({
      article_id: curArticle.id,
    });
    if (res.code === 0) {
      message.success('已回退到清洗');
      handleGetArticles();
    } else {
      message.error(res.msg);
    }
  };

  //删除该篇文章
  const handleDel = async () => {
    let res = await del_articles({
      article_id: curArticle.id,
    });
    if (res.code === 0) {
      message.success('删除成功');
      handleGetArticles();
    } else {
      message.error(res.msg);
    }
  };

  return (
    <div className="labelWrap">
      <div className="labelLeft">
        <div className="tabTitle">
          <span
            className={`${!curModel ? 'tabNav active' : 'tabNav'}`}
            onClick={() => toggleModel(false)}
          >
            未标注文档
          </span>
          <span
            className={`${curModel ? 'tabNav active' : 'tabNav'}`}
            onClick={() => toggleModel(true)}
          >
            已标注文档
          </span>
        </div>
        <div className="labelLeftConWrap">
          <div className="labelListWrap">
            {list &&
              list.length > 0 &&
              list.map((item: any, index: any) => {
                return (
                  <div
                    key={item.id}
                    onClick={() => toggleActive(item, index)}
                    className={`${active === index ? 'labelList active' : 'labelList'}`}
                  >
                    {item.title ? item.title : item.main_body}
                  </div>
                );
              })}
          </div>
          <div className="labelPagination">
            <Pagination size="small" total={total} showQuickJumper onChange={changePageSize} />
          </div>
        </div>
      </div>
      <div className="labelMain">
        <div className="articleTitle">
          {/* {curArticle.title} */}
          <Input value={title} onChange={titleChange} disabled={curModel} />
        </div>
        <div className="articleWrap">
          <div className="articleCont" ref={articleContRef} style={{ position: 'relative' }}>
            {
              <div
                className="articleHtmlBox"
                dangerouslySetInnerHTML={{ __html: articleHTML }}
                style={{ position: 'relative' }}
              ></div>
            }
          </div>
        </div>
      </div>
      <div className="labelRight">
        <div className="labelRightTopBtnBox">
          <Button onClick={goToUrl}>去上传文件</Button>
          <Button onClick={goToUrl2}>去清洗文档</Button>
        </div>
        <div className="labelRightTitle">该实体下的标签如下</div>
        <div className="labelRightInputBox">
          <Select
            style={{
              background: `${
                selectedItems !== ''
                  ? colorList[optionList.findIndex((item2: any) => item2 === selectedItems) || 0]
                  : '#fff'
              }`,
            }}
            value={selectedItems}
            defaultValue="selectedItems"
            onChange={selectChange}
            optionLabelProp="label"
            optionFilterProp="label"
            dropdownRender={(menu) => (
              <>
                {menu}
                {!curModel && (
                  <>
                    <Divider style={{ margin: '8px 0' }} />
                    <Space style={{ padding: '0 8px 4px' }}>
                      <Input
                        placeholder="请输入要添加的标签"
                        ref={inputRef}
                        value={labelName}
                        onChange={onNameChange}
                        onKeyDown={(e) => e.stopPropagation()}
                      />
                      <Button type="text" icon={<PlusOutlined />} onClick={addItem}></Button>
                    </Space>
                  </>
                )}
              </>
            )}
          >
            {optionList.map((item) => (
              <Option key={item} value={item} label={item}>
                <div className="labelselectBox">
                  <span
                    className="labelselectBox-color"
                    style={{
                      background: `${
                        colorList[optionList.findIndex((item2: any) => item2 === item) || 0]
                      }`,
                    }}
                  ></span>
                  <span className="labelselectBox-hd">{item}</span>
                  {!curModel && (
                    <span className="labelselectBox-bd">
                      <Button
                        size="small"
                        type="primary"
                        danger
                        icon={<DeleteOutlined />}
                        onClick={(e) => delItem(e, item)}
                      ></Button>
                    </span>
                  )}
                </div>
              </Option>
            ))}
          </Select>
        </div>

        {/* <div className="labelRightBtnBox">
          <Button type="primary">删除实体</Button>
        </div> */}
        <div className="labelRightTitle">该文档的名称：</div>
        <div className="labelRightInputBox">
          <Input value={title} onChange={titleChange} disabled={curModel} />
        </div>
        <div className="labelRightTitle">该文档的来源：</div>
        <div className="labelRightInputBox">
          <Input value={source} onChange={sourceChange} disabled={curModel} />
        </div>
        <div className="labelRightTitle">该文档所涵盖的领域：</div>
        <div className="labelRightInputBox">
          {/* <Input value={domain} onChange={domainChange} disabled={curModel} /> */}
          <Select
            disabled={curModel}
            mode="multiple"
            style={{ background: '#ffffff' }}
            onChange={domainChange}
            value={domain}
            options={domainList}
          />
        </div>
        <div className="labelRightTitle">该文档所涉地区：</div>
        <div className="labelRightInputBox">
          <Input value={region} onChange={regionChange} disabled={curModel} />
        </div>

        <div className="labelRightBtnBox">
          <Popconfirm
            title="提示"
            description="确定删除吗?"
            onConfirm={handleDel}
            onCancel={cancel}
            okText="是"
            cancelText="否"
          >
            <Button danger disabled={!curArticle.id} icon={<DeleteOutlined />}></Button>
          </Popconfirm>
          <Popconfirm
            title="提示"
            description="确定回退到清洗吗?"
            onConfirm={returnToClean}
            onCancel={cancel}
            okText="是"
            cancelText="否"
          >
            <Button disabled={!curArticle.id}>回退到清洗</Button>
          </Popconfirm>
          {!curModel && (
            <>
              <Popconfirm
                title="提示"
                description="确定完成吗?"
                onConfirm={submitLabel}
                onCancel={cancel}
                okText="是"
                cancelText="否"
              >
                <Button type="primary" disabled={!curArticle.id}>
                  确认完成
                </Button>
              </Popconfirm>
              {/* <Popconfirm
              title="提示"
              description="确定完成吗?"
              onConfirm={submitAllLabel}
              onCancel={cancel}
              okText="是"
              cancelText="否"
            >
              <Button className='allBtn' type="primary">全部文章-确认完成</Button>
            </Popconfirm> */}
            </>
          )}
        </div>
      </div>
      <Modal
        title="删除标签提示"
        open={isModalLabelOpen}
        onOk={handleLabelOk}
        onCancel={handleLabelCancel}
      >
        <p>
          确定要删除
          <span style={{ color: 'red', fontSize: '16px', margin: '0 10px' }}>
            {curDelLabel}
          </span>{' '}
          标签吗？
        </p>
      </Modal>
    </div>
  );
};
export default MiniModel3;
